package com.example.service.flowable.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mapper.EmpMapper;
import com.example.pojo.Emp;
import com.example.service.flowable.IEvectionService;
import com.example.vo.ResultVo;
import com.example.vo.process.EvectionDetailVo;
import com.example.vo.process.EvectionVo;
import com.example.vo.process.com.ProInst;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.*;

/**
 * 出差流程业务实现接口类
 * @author wsl
 */
@Service
public class EvectionServiceImpl implements IEvectionService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private EmpMapper empMapper;

    @Value("${process-definition-id.evection}")
    private String processDefinitionId;

    @Override
    @Transactional
    public ResultVo createEvectionProcessInstance(EvectionVo evectionVo) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("manager",evectionVo.getManager());
        variables.put("gm",evectionVo.getGm());
        variables.put("finance",evectionVo.getFinance());
        variables.put("num",evectionVo.getNum());
        variables.put("beginDate",evectionVo.getBeginDate());
        variables.put("endDate",evectionVo.getEndDate());
        variables.put("description",evectionVo.getDescription());
        Authentication.setAuthenticatedUserId(evectionVo.getStartUserId());//设置流程的发起人
        runtimeService
                .startProcessInstanceById(processDefinitionId, variables);
        return ResultVo.ok();
    }

    @Override
    public ResultVo getAssessingOfficer(String userId) {

        return null;
    }

    @Override
    public ResultVo queryMyEvectionApply(String userId) {
        //查询用户发起的出差流程
        List<HistoricProcessInstance> processInstances = historyService
                .createHistoricProcessInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .startedBy(userId)
                .orderByProcessInstanceStartTime()
                .desc()
                .includeProcessVariables()
                .list();
        List<EvectionVo> evectionVos = new ArrayList<>();
        for (HistoricProcessInstance processInstance : processInstances) {
            EvectionVo evectionVo = new EvectionVo();
            //获取流程参数
            Map<String, Object> processVariables = processInstance.getProcessVariables();
            evectionVo
                    .setProcessInstanceId(processInstance.getId())
                    .setBeginDate((Date)processVariables.get("beginDate"))
                    .setEndDate((Date)processVariables.get("endDate"))
                    .setDescription((String) processVariables.get("description"))
                    .setNum((Integer)processVariables.get("num"))
                    .setApplicDate(processInstance.getStartTime());
            if(processInstance.getEndTime()!=null){//流程已结束
                evectionVo.setEnd(true);
                evectionVo.setApproved((Boolean)processVariables.get("approved"));
            }else{
                HistoricActivityInstance historicActivityInstance = historyService
                        .createHistoricActivityInstanceQuery()
                        .processInstanceId(processInstance.getId())
                        .unfinished()
                        .singleResult();
                //获取节点处理人信息
                evectionVo.setCurrentNode(historicActivityInstance.getActivityName());
                Emp assigneeEmp = selectEmpInfo(historicActivityInstance.getAssignee());
                evectionVo.setAssigneeEmp(assigneeEmp);
            }
            evectionVos.add(evectionVo);
        }
        return ResultVo.response(evectionVos);
    }

    @Override
    public ResultVo queryEvectionApplyDetail(String processInstanceId) {
        HashSet<String> activityTyps = new HashSet<>();
        activityTyps.add("userTask");
        List<HistoricActivityInstance> userTaskNode = historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .activityTypes(activityTyps)
                .list();
        List<EvectionDetailVo> evectionDetailVos = new ArrayList<>();
        for (HistoricActivityInstance historicActivityInstance : userTaskNode) {
            //查询任务参数
            HistoricTaskInstance historicTaskInstance = historyService
                    .createHistoricTaskInstanceQuery()
                    .includeTaskLocalVariables()
                    .taskId(historicActivityInstance.getTaskId())
                    .singleResult();
            Map<String, Object> taskLocalVariables = historicTaskInstance.getTaskLocalVariables();
            //查询代理人信息
            Emp emp = empMapper.selectById(historicTaskInstance.getAssignee());
            EvectionDetailVo evectionDetailVo = new EvectionDetailVo();
            evectionDetailVo
                    .setAssignee(historicActivityInstance.getAssignee())
                    .setDuration(historicActivityInstance.getDurationInMillis())
                    .setEndTime(historicActivityInstance.getEndTime())
                    .setStartTime(historicActivityInstance.getStartTime())
                    .setNodeName(historicActivityInstance.getActivityName())
                    .setApproved((Boolean)taskLocalVariables.get("approved"))
                    .setReply((String)taskLocalVariables.get("reply"))
                    .setAssignee(historicTaskInstance.getAssignee())
                    .setAssigneeName(emp.getEmpName());
            evectionDetailVos.add(evectionDetailVo);
        }
        return ResultVo.response(evectionDetailVos);
    }

    /**
     * 查询我要处理的任务
     * @param userId
     * @return
     */
    @Override
    public ResultVo queryEvectionAuditTask(String userId) {
        //1、查询用户的任务
        List<Task> list = taskService
                .createTaskQuery()
                .processDefinitionId(processDefinitionId)
                .includeProcessVariables()
                .taskAssignee(userId)
                .list();
        List<EvectionVo> evectionVos = new ArrayList<>();
        for (Task task : list) {
            Map<String, Object> processVariables = task.getProcessVariables();
            EvectionVo evectionVo = new EvectionVo()
                    .setTaskId(task.getId())
                    .setProcessInstanceId(task.getProcessInstanceId())
                    .setBeginDate((Date) processVariables.get("beginDate"))
                    .setEndDate((Date) processVariables.get("endDate"))
                    .setDescription((String) processVariables.get("description"))
                    .setTaskName(task.getName())
                    .setNum((Integer) processVariables.get("num"));
            //2、查询用户的发起人信息
            ProcessInstance processInstance = runtimeService
                    .createProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();
            Emp startEmp = selectEmpInfo(processInstance.getStartUserId());
            evectionVo.setStartEmp(startEmp);
            evectionVos.add(evectionVo);
        }
        return ResultVo.response(evectionVos);
    }

    @Override
    public ResultVo completeEvectionAudit(String taskId, Boolean approved, String reply) {
        Map<String, Object> localVariables = new HashMap<>();
        localVariables.put("approved",approved);
        if(!StringUtils.isEmpty(reply)){
            localVariables.put("reply",reply);
        }
        taskService.setVariable(taskId,"approved",approved);
        taskService.complete(taskId,localVariables,true);
        return ResultVo.ok();
    }

    @Override
    public ResultVo queryTaskDetail(String taskId) {
        ProInst proInst = new ProInst();
        Task task = taskService
                .createTaskQuery()
                .taskId(taskId)
                .singleResult();
        String processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .includeProcessVariables()
                .singleResult();
        String startUserId = processInstance.getStartUserId();
        Emp emp = selectEmpInfo(startUserId);
        proInst
                .setCreateTime(processInstance.getStartTime())
                .setProcessInstanceId(processInstanceId)
                .setVariables(processInstance.getProcessVariables())
                .setStartUserId(processInstance.getStartUserId())
                .setStartUser(emp.getEmpName());
        return ResultVo.response(proInst);
    }

    /**
     * 查询流程任务处理者信息
     * @param empId
     * @return
     */
    public Emp selectEmpInfo(String empId){
        QueryWrapper<Emp> wrapper = new QueryWrapper<Emp>().select("id,emp_name").eq("id", empId);
        return empMapper.selectOne(wrapper);
    }

//    /**
//     * 查询用户的发起人信息
//     * @param empId
//     * @return
//     */
//    public Emp selectStartEmp(String empId){
//        QueryWrapper<Emp> wrapper = new QueryWrapper<Emp>().select("id,emp_name").eq("id", empId);
//        return empMapper.selectOne(wrapper);
//    }
}
